<?php

declare(strict_types=1);

namespace Dreamcat\ApiDocTest\TestCases;

use Dreamcat\ApiDoc\ApiGenerators\ApiDocGenerator;
use Dreamcat\ApiDoc\Enums\SwaggerJsonMode;
use Dreamcat\ApiDoc\Popo\RouterEntranceDefinition;
use Dreamcat\ApiDoc\Swagger\Define2Swagger;
use Dreamcat\ApiDocTest\Demo\Popo\IgnoreTypeInterface;
use Dreamcat\ApiDocTest\Demo\Route\TestCaseFactory;
use Dreamcat\ApiDocTest\Utils\GuzzleUriRetriever;
use JsonSchema\Constraints\Factory;
use JsonSchema\Validator;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\RequestInterface;
use ReflectionException;
use Throwable;

/**
 * 接口文档生成器测试
 * @author vijay
 */
class ApiGenTest extends TestCase
{
    /**
     * @throws ReflectionException
     */
    public function testApiGenerators()
    {
        $datas = TestCaseFactory::getList();
        $factory = new Factory();
        $factory->getUriRetriever()
            ->setUriRetriever(new GuzzleUriRetriever());
        $validator = new Validator($factory);

        $schemas = [
            SwaggerJsonMode::SWAGGER => json_decode(
                file_get_contents(__DIR__ . "/../../resources/JsonSchema/swagger2.json")
            ),
            SwaggerJsonMode::YAPI => json_decode(
                file_get_contents(__DIR__ . "/../../resources/JsonSchema/yapi-swagger.json")
            ),
        ];
        $generator = new ApiDocGenerator();
        self::assertEquals([RequestInterface::class], $generator->getIgnoreTypes());
        self::assertEquals($generator, $generator->clearIgnoreTypes());
        self::assertEmpty($generator->getIgnoreTypes());
        $generator->addIgnoreType(IgnoreTypeInterface::class);
        $generator->addIgnoreType(RequestInterface::class);
        foreach ($datas as $data) {
            /** @var RouterEntranceDefinition $routeDef */
            $routeDef = $data[0];
            $routeKey = "{$routeDef->getUri()}::{$routeDef->getMethod()}";
            $tools = new Define2Swagger("yapi-server");
            if ($data[2]) {
                $tools->setSwaggerJsonMode(SwaggerJsonMode::from($data[2]));
            }
            $swaggerJson = $tools
                ->addApiDefine($generator->parseApi($routeDef))
                ->getJson();
            $jsonObj = json_decode(json_encode($swaggerJson));
            $msg = [];
            try {
                $validator->validate($jsonObj, $schemas[$tools->getSwaggerJsonMode()->getValue()]);
                $ok = $validator->isValid();
            } catch (Throwable $throwable) {
                $ok = false;
                $msg[] = $throwable->getMessage();
            }

            if (!$ok) {
                foreach ($validator->getErrors() as $error) {
                    $msg[] = sprintf("[%s] %s", $error['property'], $error['message']);
                }
                self::fail($routeKey . " 得到的 swagger json 不合法 " . implode("; ", $msg));
            }
            $actualJosn = $swaggerJson["paths"];
            self::assertEquals($routeDef->getUri(), array_keys($actualJosn)[0], "{$routeKey} 输出的路径不正确");
            self::assertEquals(
                strtolower($routeDef->getMethod()),
                array_keys($actualJosn[$routeDef->getUri()])[0],
                "{$routeKey} 输出的method不正确"
            );
            self::assertEquals(
                $data[1],
                json_decode(json_encode($actualJosn[$routeDef->getUri()][strtolower($routeDef->getMethod())]), true),
                "{$routeKey} 输出的文档不正确"
            );
        }
    }
}

# end of file
